package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.ServiceItem;
import cn.wolfcode.car.business.mapper.BpmnInfoMapper;
import cn.wolfcode.car.business.mapper.CarPackageAuditMapper;
import cn.wolfcode.car.business.mapper.ServiceItemMapper;
import cn.wolfcode.car.business.query.ServiceItemQuery;
import cn.wolfcode.car.business.service.IServiceItemService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.common.util.Convert;
import cn.wolfcode.car.common.util.StringUtils;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class ServiceItemServiceImpl extends ServiceImpl<ServiceItemMapper, ServiceItem> implements IServiceItemService {

    @Autowired
    private ServiceItemMapper serviceItemMapper;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private BpmnInfoMapper bpmnInfoMapper;
    @Autowired
    private CarPackageAuditMapper carPackageAuditMapper;


    @Override
    public TablePageInfo<ServiceItem> query(ServiceItemQuery qo) {
        // 分页信息
        IPage<ServiceItem> page = new Page<>(qo.getPageNum(), qo.getPageSize());
        // 过滤信息
        LambdaQueryWrapper<ServiceItem> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.isNotEmpty(qo.getName()), ServiceItem::getName, qo.getName())    // 名称
                .eq(StringUtils.isNotNull(qo.getCarPackage()), ServiceItem::getCarPackage, qo.getCarPackage())     // 是否套餐
                .eq(StringUtils.isNotNull(qo.getServiceCatalog()), ServiceItem::getServiceCatalog, qo.getServiceCatalog())     // 服务分类
                .eq(StringUtils.isNotNull(qo.getAuditStatus()), ServiceItem::getAuditStatus, qo.getAuditStatus())   // 审核状态
                .eq(StringUtils.isNotNull(qo.getSaleStatus()), ServiceItem::getSaleStatus, qo.getSaleStatus());    // 上架状态

        TablePageInfo<ServiceItem> info = new TablePageInfo<>(super.page(page, wrapper).getRecords());
        info.setTotal(super.count());   // 设置总数
        return info;
    }


    @Override
    public boolean save(ServiceItem serviceItem) {
        // 若为非套餐，设置审核状态为无需审核
        if (ServiceItem.CARPACKAGE_NO.equals(serviceItem.getCarPackage())) {
            serviceItem.setSaleStatus(ServiceItem.AUDITSTATUS_NO_REQUIRED);
        }
        // 若为套餐，设置审核状态为初始化
        if (ServiceItem.CARPACKAGE_YES.equals(serviceItem.getCarPackage())) {
            serviceItem.setSaleStatus(ServiceItem.AUDITSTATUS_INIT);
        }
        // 设置创建时间
        serviceItem.setCreateTime(new Date());
        // 设置是否上架为未上架
        serviceItem.setSaleStatus(ServiceItem.SALESTATUS_OFF);

        return serviceItemMapper.insert(serviceItem) > 0;
    }


    @Override
    public void update(ServiceItem serviceItem) {
        // 根据id从数据库中查出需要修改的数据，并进行判断
        ServiceItem oldObj = this.getById(serviceItem.getId());
        // 已上架，抛出异常
        if (ServiceItem.SALESTATUS_ON.equals(oldObj.getSaleStatus())) {
            throw new BusinessException("服务单项已经上架，不允许修改！");
        }
        // 无需判断是否为套餐，因为处于审核中的都是套餐
        // 审核状态为审核中，抛出异常
        if (ServiceItem.AUDITSTATUS_AUDITING.equals(oldObj.getAuditStatus())) {
            throw new BusinessException("套餐正在审核中，不允许修改！");
        }
        // 执行到这里，则说明服务单项未上架，并且 为套餐不是处于审核中 或 不为套餐
        // 若套餐为审核通过，则审核状态设置为初始化
        if (ServiceItem.AUDITSTATUS_APPROVED.equals(oldObj.getAuditStatus())){
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        } else {    // 否则，设置为原来的审核状态
            serviceItem.setAuditStatus(oldObj.getAuditStatus());
        }
        // 设置服务单项为未上架，避免传入恶意数据导致出错
        serviceItem.setSaleStatus(oldObj.getSaleStatus());
        // 将查出的创建时间设置到对象中
        serviceItem.setCreateTime(oldObj.getCreateTime());

        serviceItemMapper.updateById(serviceItem);
        // serviceItemMapper.updateByPrimaryKey(serviceItem);
    }

    @Override
    public void deleteBatch(String ids) {
        // 将字符串转为Long数组
        Long[] dictIds = Convert.toLongArray(ids);
        for (Long dictId : dictIds) {
            serviceItemMapper.deleteById(dictId);
        }
    }

    @Override
    public List<ServiceItem> list() {
        return serviceItemMapper.selectList(null);
        // return serviceItemMapper.selectAll();
    }

    @Override
    public void saleOn(Long id) {
        // 根据指定 id 获取服务单项
        ServiceItem serviceItem = this.getById(id);
        // 套餐，并且没有通过审核，抛出异常
        if (ServiceItem.CARPACKAGE_YES.equals(serviceItem.getCarPackage())
                && !ServiceItem.AUDITSTATUS_APPROVED.equals(serviceItem.getAuditStatus())) {
            throw new RuntimeException("套餐需要审核通过才能上架！");
        }
        LambdaUpdateWrapper<ServiceItem> wrapper = Wrappers.lambdaUpdate();
        // 修改状态为上架
        wrapper.eq(ServiceItem::getId, id)
                .set(ServiceItem::getSaleStatus, ServiceItem.SALESTATUS_ON);
        serviceItemMapper.update(null, wrapper);
        // serviceItemMapper.changeSaleStatus(id, ServiceItem.SALESTATUS_ON);
    }

    @Override
    public void saleOff(Long id) {
        LambdaUpdateWrapper<ServiceItem> wrapper = Wrappers.lambdaUpdate();
        // 修改状态为下架
        wrapper.eq(ServiceItem::getId, id)
                .set(ServiceItem::getSaleStatus, ServiceItem.SALESTATUS_OFF);
        serviceItemMapper.update(null, wrapper);
        // serviceItemMapper.changeSaleStatus(id, ServiceItem.SALESTATUS_OFF);
    }

    @Override
    @Transactional
    public void startAudit(Long id, Long bpmnInfoId, Long director, Long finance, String info) {
        // 合理性判断
        ServiceItem serviceItem = this.getById(id);
        // 服务单项下架、套餐、初始化或重新发起才能进行提交审核
        if (ServiceItem.SALESTATUS_ON.equals(serviceItem.getSaleStatus())
            || ServiceItem.CARPACKAGE_NO.equals(serviceItem.getCarPackage())
            || ServiceItem.AUDITSTATUS_AUDITING.equals(serviceItem.getAuditStatus())
            || ServiceItem.AUDITSTATUS_APPROVED.equals(serviceItem.getAuditStatus())
            || ServiceItem.AUDITSTATUS_NO_REQUIRED.equals(serviceItem.getAuditStatus()))
        {
            throw new BusinessException("非法操作！");
        }
        // 服务单项审核状态改为审核中
        serviceItemMapper.changeAuditStatus(id, ServiceItem.AUDITSTATUS_AUDITING);
        // 创建套餐审核对象，并设置值
        CarPackageAudit audit = new CarPackageAudit();
        audit.setServiceItemId(id); // 服务单项id
        audit.setServiceItemName(serviceItem.getName());    // 服务单项名称
        audit.setServiceItemInfo(serviceItem.getInfo());    // 服务单项备注信息
        audit.setServiceItemPrice(serviceItem.getDiscountPrice());  // 服务单项审核价格
        audit.setCreator(ShiroUtils.getUser().getUserName());   // 创建者
        audit.setAuditorId(director); // 当前审核人id
        audit.setBpmnInfoId(bpmnInfoId);    // 关联流程id
        audit.setInfo(info);    // 备注
        audit.setCreateTime(new Date());    // 创建时间
        // 保存
        carPackageAuditMapper.insert(audit);

        // 获取流程定义key
        String processKey = bpmnInfoMapper.selectByPrimaryKey(bpmnInfoId).getActProcessKey();
        Map<String, Object> map = new HashMap<>();
        if (director != null) {
            map.put("director", director.toString());
        }
        if (finance != null) {
            map.put("finance", finance.toString());
        }
        map.put("discountPrice", serviceItem.getDiscountPrice().longValue());
        // 创建一个流程实例，绑定业务key
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processKey, audit.getId().toString(), map);
        // 更新套餐审核对象的流程实例id
        audit.setInstanceId(processInstance.getId());
        carPackageAuditMapper.updateInstanceId(audit);
    }
}
